msg_tool\scripts\softpal\img\pgd/
ge.rs1use super::base::*;
2use crate::ext::io::*;
3use crate::scripts::base::*;
4use crate::types::*;
5use crate::utils::struct_pack::*;
6use anyhow::Result;
7use std::io::{Read, Seek};
8
9#[derive(Debug)]
10pub struct PgdGeBuilder {}
11
12impl PgdGeBuilder {
13 pub fn new() -> Self {
14 Self {}
15 }
16}
17
18impl ScriptBuilder for PgdGeBuilder {
19 fn default_encoding(&self) -> Encoding {
20 Encoding::Cp932
21 }
22
23 fn build_script(
24 &self,
25 buf: Vec<u8>,
26 _filename: &str,
27 _encoding: Encoding,
28 _archive_encoding: Encoding,
29 config: &ExtraConfig,
30 _archive: Option<&Box<dyn Script>>,
31 ) -> Result<Box<dyn Script>> {
32 Ok(Box::new(PgdGe::new(MemReader::new(buf), config)?))
33 }
34
35 fn extensions(&self) -> &'static [&'static str] {
36 &["pgd"]
37 }
38
39 fn script_type(&self) -> &'static ScriptType {
40 &ScriptType::SoftpalPgdGe
41 }
42
43 fn is_image(&self) -> bool {
44 true
45 }
46
47 fn is_this_format(&self, _filename: &str, buf: &[u8], buf_len: usize) -> Option<u8> {
48 if buf_len >= 4 && buf.starts_with(b"GE \0") {
49 return Some(20);
50 }
51 None
52 }
53
54 fn can_create_image_file(&self) -> bool {
55 true
56 }
57
58 fn create_image_file<'a>(
59 &'a self,
60 data: ImageData,
61 mut writer: Box<dyn WriteSeek + 'a>,
62 options: &ExtraConfig,
63 ) -> Result<()> {
64 let header = PgdGeHeader {
65 offset_x: 0,
66 offset_y: 0,
67 width: data.width,
68 height: data.height,
69 canvas_width: data.width,
70 canvas_height: data.height,
71 mode: 3,
72 _unk: 0,
73 };
74 writer.write_all(b"GE \0")?;
75 header.pack(&mut writer, false, Encoding::Utf8)?;
76 PgdWriter::new(data, options.pgd_fake_compress)
77 .with_method(3)
78 .pack_ge(&mut writer)?;
79 Ok(())
80 }
81}
82
83#[derive(Debug)]
84pub struct PgdGe {
85 header: PgdGeHeader,
86 data: ImageData,
87 fake_compress: bool,
88}
89
90impl PgdGe {
91 pub fn new<T: Read + Seek>(mut input: T, config: &ExtraConfig) -> Result<Self> {
92 let mut magic = [0u8; 4];
93 input.read_exact(&mut magic)?;
94 if &magic != b"GE \0" {
95 return Err(anyhow::anyhow!("Not a valid PGD GE image"));
96 }
97 let header = PgdGeHeader::unpack(&mut input, false, Encoding::Utf8)?;
98 let reader = PgdReader::with_ge_header(input, &header)?;
99 let data = reader.unpack_ge()?;
100 Ok(Self {
101 header,
102 data,
103 fake_compress: config.pgd_fake_compress,
104 })
105 }
106}
107
108impl Script for PgdGe {
109 fn default_output_script_type(&self) -> OutputScriptType {
110 OutputScriptType::Json
111 }
112
113 fn default_format_type(&self) -> FormatOptions {
114 FormatOptions::None
115 }
116
117 fn is_image(&self) -> bool {
118 true
119 }
120
121 fn export_image(&self) -> Result<ImageData> {
122 Ok(self.data.clone())
123 }
124
125 fn import_image<'a>(
126 &'a self,
127 data: ImageData,
128 mut file: Box<dyn WriteSeek + 'a>,
129 ) -> Result<()> {
130 let mut header = self.header.clone();
131 if data.height != self.data.height {
132 return Err(anyhow::anyhow!(
133 "Image height does not match: expected {}, got {}",
134 self.data.height,
135 data.height
136 ));
137 }
138 if data.width != self.data.width {
139 return Err(anyhow::anyhow!(
140 "Image width does not match: expected {}, got {}",
141 self.data.width,
142 data.width
143 ));
144 }
145 header.mode = 3;
146 file.write_all(b"GE \0")?;
147 header.pack(&mut file, false, Encoding::Utf8)?;
148 PgdWriter::new(data, self.fake_compress)
149 .with_method(3)
150 .pack_ge(&mut file)?;
151 Ok(())
152 }
153}